#include <QtCore/QtEndian>
#include <QtCore/QFile>
#include "logparams/log_message_templates.h"
#include "logdecoder/log_decoder.h"
#include "logdecoder/log_decoder_p.h"
#include "global.h"

namespace smsrouter {

LogDecoderPrivate::LogDecoderPrivate() : QObject(0), thread(new QThread(this)) {
  moveToThread(thread);
  connect(this, SIGNAL(sigDecode(binaryrpc::ServerMessage *)),
          this, SLOT(decode(binaryrpc::ServerMessage *)));
}

LogDecoderPrivate::~LogDecoderPrivate() {

}

bool LogDecoderPrivate::decode(
  const QByteArray &buff, int &pos, QMultiHash<int, QVariant> &parameters) {

  while(pos < buff.size()) {
    int param_code(0);
    if(decode(buff, pos, param_code) == false) {
      return false;
    }

    QVariant param_value;
    if(decode(buff, pos, param_value) == false) {
      return false;
    }

    parameters.insert(param_code, param_value);
  }

  return true;
}

bool LogDecoderPrivate::decode(
  const QByteArray &buff, int &pos, QVariant &val) {
  int type(0);

  if(decode(buff, pos, type) == false) {
    return false;
  }

  switch(type) {
    case QVariant::Bool: {
      bool value(false);
      if(decode(buff, pos, value) == false) {
        return false;
      }
      val = value;
      break;
    }
    case QVariant::Char: {
      char value(0x00);
      if(decode(buff, pos, value) == false) {
        return false;
      }
      val = value;
      break;
    }
    case QVariant::Int: {
      int value(0);
      if(decode(buff, pos, value) == false) {
        return false;
      }
      val = value;
      break;
    }
    case QVariant::UInt: {
      quint32 value(0);
      if(decode(buff, pos, value) == false) {
        return false;
      }
      val = value;
      break;
    }
    case QVariant::String: {
      QString value;
      if(decode(buff, pos, value) == false) {
        return false;
      }
      val = value;
      break;
    }
    case QVariant::ByteArray: {
      int size;
      if(decode(buff, pos, size) == false) {
        return false;
      }
      QByteArray value;
      if(decode(buff, pos, value, size) == false) {
        return false;
      }
      val = value;
      break;
    }
    default:
      return false;
  }

  return true;
}

bool LogDecoderPrivate::decode(const QByteArray &buff, int &pos, bool &p) {
  char tmp;
  if(decode(buff, pos, tmp)) {
    p = (tmp == 0x01) ? true : false;
    return true;
  }
  return false;
}

bool LogDecoderPrivate::decode(const QByteArray &buff, int &pos, char &p) {
  if(pos + 1 > buff.size())
    return false;

  p = buff[pos++];

  return true;
}

bool LogDecoderPrivate::decode(const QByteArray &buff, int &pos, int &p) {
  if(pos + 4 > buff.size()) return false;

  int v(0);
  char *c_pt(reinterpret_cast<char *>(&v));
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *c_pt = buff[pos++];
  p = qFromBigEndian(v);

  return true;
}

bool LogDecoderPrivate::decode(const QByteArray &buff, int &pos, uint &p) {
  if(pos + 4 > buff.size()) return false;

  uint v(0);
  char *c_pt(reinterpret_cast<char *>(&v));
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *c_pt = buff[pos++];
  p = qFromBigEndian(v);

  return true;
}

bool LogDecoderPrivate::decode(const QByteArray &buff, int &pos, quint64 &p) {
  if(pos + 8 > buff.size())
    return false;

  qint64 v(0);
  char *c_pt(reinterpret_cast<char *>(&v));
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *(c_pt++) = buff[pos++];
  *c_pt = buff[pos++];
  p = qFromBigEndian(v);

  return true;
}


bool LogDecoderPrivate::decode(
  const QByteArray &buff, int &pos, QByteArray &p, int length) {
  if((pos + length) > buff.size())
    return false;

  p.resize(length);

  if(length > 0) {
    p = buff.mid(pos, length);
    pos += length;
  }

  return true;
}

bool LogDecoderPrivate::decode(const QByteArray &buff, int &pos, QString &p) {
  int temp_pos(pos);
  int data_size(buff.size());
  while(1) {
    if(temp_pos >= data_size)
      return false;
    if(buff[temp_pos++] == '\0')
      break;
  }
  p.clear();
  temp_pos -= pos + 1;
  p.resize(temp_pos);
  for(int i = 0; i < temp_pos; i++)
    p[i] = buff[pos++];
  pos++;
  return true;
}

void LogDecoderPrivate::decode(const QString &file_name,
                               quint64 start_date,
                               quint64 end_date,
                               quint32 &now_pos,
                               quint32 start_pos,
                               quint32 end_pos,
                               smslog::LogLevel log_level,
                               int cls,
                               int obj,
                               const QString &message,
                               LogDecodedMessages &decoded_messages) {
  QFile file(file_name);
  if(file.open(QIODevice::ReadOnly)) {
    while(!file.atEnd()) {
      QByteArray header(file.read(25));

      if(header.size() < 25) {
        return;
      }

      int pos(0);
      quint64 timestamp;
      char log_level_char;
      int _application;
      int _class;
      int _object;
      int body_size;

      decode(header, pos, timestamp);
      decode(header, pos, log_level_char);
      smslog::LogLevel level((smslog::LogLevel)log_level_char);
      decode(header, pos, _application);
      decode(header, pos, _class);
      decode(header, pos, _object);
      decode(header, pos, body_size);

      QByteArray body(file.read(body_size));

      if(body.size() < body_size) {
        return;
      }

      if(timestamp >= start_date &&
         timestamp <= end_date &&
         log_level >= level &&
         _application == logapp::SMS_ROUTER &&
         (cls == -1 || cls == _class) &&
         (obj == -1 || obj == _object)) {
        int message_code(0);

        pos = 0;

        if(decode(body, pos, message_code)) {
          QMultiHash<int, QVariant> message_params;

          if(decode(body, pos, message_params)) {
            QString log_message_string;
            if(createLogMessageString(log_message_string,
                                      message_code,
                                      message_params)) {
              if(message.isEmpty() ||
                 log_message_string.contains(message, Qt::CaseInsensitive)) {

                if(now_pos >= start_pos && now_pos < end_pos) {
                  decoded_messages.messages.push_back(
                    new LogDecodedMessage(now_pos + 1,
                                          timestamp,
                                          level,
                                          _class,
                                          _object,
                                          log_message_string));
                }

                now_pos++;

                decoded_messages.num_all_messages++;
              }
            }
          }
        }
      }
    }
  }
}

QString LogDecoderPrivate::paramToString(const QVariant &p) const {
  switch(p.type()) {
    case QVariant::Bool:
      return QString(p.toBool());
    case QVariant::Char:
      return QString(p.toChar());
    case QVariant::Int:
      return QString::number(p.toInt());
    case QVariant::UInt:
      return QString::number(p.toUInt());
    case QVariant::LongLong:
      return QString::number(p.toLongLong());
    case QVariant::ULongLong:
      return QString::number(p.toULongLong());
    case QVariant::Double:
      return QString::number(p.toDouble());
    case QVariant::String:
      return p.toString();
    case QVariant::ByteArray:
      return QString(p.toByteArray().toHex());
    default:
      return QString();
  }
}

bool LogDecoderPrivate::createLogMessageString(
  QString &message,
  int message_id,
  const QMultiHash<int, QVariant> &message_parameters) {
  switch(message_id) {
    case smsrouter::logmsgcodes::UD_QT_LOG_MSG: {
      if(message_parameters.size() != 1) {
        return false;
      }

      message = QString(smsrouter::logtemplates::UD_QT_LOG_MSG);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::UD_CONFIG_ACCESS_ERR: {
      if(message_parameters.size() != 1) {
        return false;
      }

      message = QString(smsrouter::logtemplates::UD_CONFIG_ACCESS_ERR);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::UD_CONFIG_PARSE_ERR: {
      if(message_parameters.size() != 1) {
        return false;
      }

      message = QString(smsrouter::logtemplates::UD_CONFIG_PARSE_ERR);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::UD_CONFIG_READ_ERR: {
      if(message_parameters.size() != 1) {
        return false;
      }

      message = QString(smsrouter::logtemplates::UD_CONFIG_READ_ERR);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_STARTED_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::K_STARTED_STATE);
      break;
    }
    case smsrouter::logmsgcodes::K_STOPED_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::K_STOPED_STATE);
      break;
    }
    case smsrouter::logmsgcodes::K_STOPING_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::K_STOPING_STATE);
      break;
    }
    case smsrouter::logmsgcodes::K_STARTING_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::K_STARTING_STATE);
      break;
    }
    case smsrouter::logmsgcodes::K_ERROR_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::K_ERROR_STATE);
      break;
    }
    case smsrouter::logmsgcodes::K_INIT_ERR: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::K_INIT_ERR);
      break;
    }
    case smsrouter::logmsgcodes::K_SRC_SUBMIT_ROUTED: {
      if(message_parameters.size() != 3) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_SRC_SUBMIT_ROUTED);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        message.replace(QString("$%1$").arg(i.key()), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_TRANSFORM_SRC_SUBMIT: {
      if(message_parameters.size() != 10) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_TRANSFORM_SRC_SUBMIT);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_FILTER_SRC_SUBMIT: {
      if(message_parameters.size() != 2) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_FILTER_SRC_SUBMIT);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_FILTER_DEST_SUBMIT: {
      if(message_parameters.size() != 2) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_FILTER_DEST_SUBMIT);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_TRANSFORM_SRC_DELIVER: {
      if(message_parameters.size() != 10) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_TRANSFORM_SRC_DELIVER);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_BILLING_CL_OPEN: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_BILLING_CL_OPEN);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_BILLING_CL_CLOSE: {
      if(message_parameters.size() != 2) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_BILLING_CL_CLOSE);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_BILLING_CL_ERROR: {
      if(message_parameters.size() != 3) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_BILLING_CL_ERROR);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_BILLING_CL_DONE: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_BILLING_CL_DONE);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_BILLING_CL_FAULT: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_BILLING_CL_FAULT);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_BILLING_CL_REQUEST_1: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_BILLING_CL_REQUEST_1);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::K_BILLING_CL_REQUEST_2: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::K_BILLING_CL_REQUEST_2);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::M_STARTED_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::M_STARTED_STATE);
      break;
    }
    case smsrouter::logmsgcodes::M_STOPED_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::M_STOPED_STATE);
      break;
    }
    case smsrouter::logmsgcodes::M_STOPING_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::M_STOPING_STATE);
      break;
    }
    case smsrouter::logmsgcodes::M_STARTING_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::M_STARTING_STATE);
      break;
    }
    case smsrouter::logmsgcodes::M_ERROR_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::M_ERROR_STATE);
      break;
    }
    case smsrouter::logmsgcodes::M_NOT_FOUND_TABLE_SRC_SM: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::M_NOT_FOUND_TABLE_SRC_SM);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::M_NOT_FOUND_TABLE_SRC_DM: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::M_NOT_FOUND_TABLE_SRC_DM);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::M_NOT_FOUND_TABLE_DST_SM: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::M_NOT_FOUND_TABLE_DST_SM);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::M_NOT_FOUND_TABLE_DST_DM: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::M_NOT_FOUND_TABLE_DST_SM);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_STARTED_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::SM_STARTED_STATE);
      break;
    }
    case smsrouter::logmsgcodes::SM_STOPED_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::SM_STOPED_STATE);
      break;
    }
    case smsrouter::logmsgcodes::SM_STOPING_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::SM_STOPING_STATE);
      break;
    }
    case smsrouter::logmsgcodes::SM_STARTING_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::SM_STARTING_STATE);
      break;
    }
    case smsrouter::logmsgcodes::SM_ERROR_STATE: {
      if(!message_parameters.empty()) {
        return false;
      }
      message = QString(smsrouter::logtemplates::SM_ERROR_STATE);
      break;
    }
    case smsrouter::logmsgcodes::SM_LISTEN_SRC_SERVER: {
      if(message_parameters.size() != 2) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_LISTEN_SRC_SERVER);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_NOT_LISTEN_SRC_SERVER: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_NOT_LISTEN_SRC_SERVER);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_OPEN_SRC_SESSION: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_OPEN_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_OPEN_DEST_SESSION: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_OPEN_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_CLOSE_SRC_SESSION: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_CLOSE_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_CLOSE_DEST_SESSION: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_CLOSE_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_RESTART_DEST_SESS: {
      if(message_parameters.size() != 2) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_RESTART_DEST_SESS);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_NOT_RESTART_DEST_SESS: {
      if(message_parameters.size() != 1) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_NOT_RESTART_DEST_SESS);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_ERROR_SRC_SESSION: {
      if(message_parameters.size() != 7) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_ERROR_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_ERROR_DEST_SESSION: {
      if(message_parameters.size() != 7) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_ERROR_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_SEND_DEST_SESSION: {
      if(message_parameters.size() != 7) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_SEND_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_NOT_SEND_DEST_SESSION: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_NOT_SEND_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_SEND_SRC_SESSION: {
      if(message_parameters.size() != 7) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_SEND_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_NOT_SEND_SRC_SESSION: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_NOT_SEND_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_RECEIVE_SRC_SESSION: {
      if(message_parameters.size() != 7) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_RECEIVE_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_RECEIVE_DEST_SESSION: {
      if(message_parameters.size() != 7) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_RECEIVE_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_INIT_SRC_SESSION: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_INIT_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_INIT_DEST_SESSION: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_INIT_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_INACT_SRC_SESSION: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_INACT_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_INACT_DEST_SESSION: {
      if(message_parameters.size() != 5) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_INACT_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_CREATE_SRC_SESSION: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_CREATE_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_CREATE_DEST_SESSION: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_CREATE_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_DESTROY_SRC_SESSION: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_DESTROY_SRC_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::SM_DESTROY_DEST_SESSION: {
      if(message_parameters.size() != 4) {
        return false;
      }

      message = QString(smsrouter::logtemplates::SM_DESTROY_DEST_SESSION);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::CONF_NOT_FOUND_KEY_1: {
      if(message_parameters.size() != 1) {
        return false;
      }

      message = QString(smsrouter::logtemplates::CONF_NOT_FOUND_KEY_1);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::CONF_NOT_FOUND_KEY_1_2: {
      if(message_parameters.size() != 2) {
        return false;
      }

      message = QString(smsrouter::logtemplates::CONF_NOT_FOUND_KEY_1_2);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    case smsrouter::logmsgcodes::ERROR_EXEC_SQL_QUERY: {
      if(message_parameters.size() != 3) {
        return false;
      }

      message = QString(smsrouter::logtemplates::ERROR_EXEC_SQL_QUERY);

      for(QMultiHash<int, QVariant>::const_iterator i =
            message_parameters.constBegin();
          i != message_parameters.constEnd();
          i++) {
        QString sub_str(QString("$%1$").arg(i.key()));

        message.replace(
          message.indexOf(sub_str), sub_str.size(), paramToString(i.value()));
      }
      break;
    }
    default:
      return false;
  }

  return true;
}

LogDecodedMessages LogDecoderPrivate::decode(quint64 start_date,
                                             quint64 end_date,
                                             quint32 page,
                                             quint32 page_size,
                                             smslog::LogLevel log_level,
                                             int cls,
                                             int obj,
                                             const QString &message) {
  QDateTime start_date_0(QDateTime::fromMSecsSinceEpoch(start_date));
  QDateTime end_date_0(QDateTime::fromMSecsSinceEpoch(end_date));
  start_date_0.setTime(QTime(0, 0, 0, 0));
  end_date_0.setTime(QTime(0, 0, 0, 0));

  LogDecodedMessages decoded_messages;

  quint32 now_pos(0);
  quint32 start_pos((page - 1) * page_size);
  quint32 end_pos(page * page_size);

  while(start_date_0 <= end_date_0) {
    QString file_name(QString("%1/").arg(LOG_FILE_PATH) +
                      QString(APP_NAME) +
                      start_date_0.toString("_dd_MM_yyyy") +
                      ".log");

    decode(file_name,
           start_date,
           end_date,
           now_pos,
           start_pos,
           end_pos,
           log_level,
           cls,
           obj,
           message,
           decoded_messages);

    start_date_0 = start_date_0.addDays(1);
  }

  return decoded_messages;
}

void LogDecoderPrivate::decode(binaryrpc::ServerMessage *message) {
  QVariantList parameters(message->parameters());

  bool success(parameters.size() == 8);

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  quint64 start_date(parameters[0].toULongLong(&success));

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  quint64 end_date(parameters[1].toULongLong(&success));

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  quint32 page(parameters[2].toUInt(&success));

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  quint32 page_size(parameters[3].toUInt(&success));

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  smslog::LogLevel log_level((smslog::LogLevel)parameters[4].toInt(&success));

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  int cls(parameters[5].toInt(&success));

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  int obj(parameters[6].toInt(&success));

  if(!success) {
    message->fault(BRPC_ERR_CODE_NOT_FOUND, BRPC_ERR_CODE_NOT_FOUND_D);
    message->deleteLater();
    return;
  }

  QString message_str(parameters[7].toString());

  LogDecodedMessages decoded_messages(
    decode(start_date,
           end_date,
           page,
           page_size,
           log_level,
           cls,
           obj,
           message_str));

  QVariantMap messages_map;

  messages_map.insert("count", decoded_messages.num_all_messages);

  QVariantList find_messages_list;

  for(int i = 0; i < decoded_messages.messages.size(); i++) {
    QVariantList find_message_pam;
    LogDecodedMessage *decoded_message(decoded_messages.messages[i]);
    find_message_pam.push_back(decoded_message->id);
    find_message_pam.push_back(decoded_message->date);
    find_message_pam.push_back((char)decoded_message->log_level);
    find_message_pam.push_back(decoded_message->cls);
    find_message_pam.push_back(decoded_message->obj);
    find_message_pam.push_back(decoded_message->message);
    find_messages_list.push_back(find_message_pam);
  }

  messages_map.insert("messages", find_messages_list);

  message->done(messages_map);
}

LogDecoder::LogDecoder() : p(new LogDecoderPrivate) {
  p->thread->start();
}

LogDecoder::~LogDecoder() {
  if(p) {
    if(p->thread) {
      if(p->thread->isRunning()) {
        p->thread->quit();
        p->thread->wait();
      }
    }
    delete p;
    p = 0;
  }
}

void LogDecoder::decode(binaryrpc::ServerMessage *message) {
  emit p->sigDecode(message);
}

} // namespace smsrouter
